package com.syqc.monitor.ui.region

import android.Manifest
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.location.Location
import android.util.LruCache
import android.view.Gravity
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.activity.viewModels
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import autodispose2.autoDispose
import com.amap.api.maps.AMap
import com.amap.api.maps.AMapUtils
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.model.BitmapDescriptor
import com.amap.api.maps.model.BitmapDescriptorFactory
import com.amap.api.maps.model.CircleOptions
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.LatLngBounds
import com.amap.api.maps.model.Marker
import com.amap.api.maps.model.PolygonOptions
import com.amap.api.maps.model.PolylineOptions
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.google.gson.reflect.TypeToken
import com.gyf.immersionbar.ktx.immersionBar
import com.permissionx.guolindev.PermissionX
import com.syqc.maps.utils.MapUtil
import com.syqc.monitor.ui.carinfo.CarInfoActivity
import com.syqc.adapter.CarInfoAdapter
import com.syqc.adapter.OperInfoAdapter
import com.syqc.base.BaseMapLocationActivity
import com.syqc.comlib.AppConfigs
import com.syqc.comlib.GuideControl
import com.syqc.comlib.MenuKey
import com.syqc.comlib.UserConstant
import com.syqc.comlib.databinding.IncludeToolbarBinding
import com.syqc.comlib.rx.filterFast
import com.syqc.comlib.utils.GsonUtil
import com.syqc.comlib.utils.ToolbarHelper
import com.syqc.comlib.utils.loadStringImgError
import com.syqc.comlib.utils.showToast
import com.syqc.comlib.utils.startActivityTo
import com.syqc.comlib.utils.toast
import com.syqc.comlib.utils.toastLong
import com.syqc.entity.GpsDetail
import com.syqc.entity.PoiStati
import com.syqc.entity.Point
import com.syqc.login.FunKey
import com.syqc.login.FunType
import com.syqc.login.InfoSetModel
import com.syqc.login.LocationStatusModel
import com.syqc.maps.clusters.Cluster
import com.syqc.maps.clusters.ClusterItem
import com.syqc.maps.clusters.ClusterListener
import com.syqc.maps.clusters.ClusterOverlay
import com.syqc.maps.clusters.ClusterRender
import com.syqc.maps.clusters.MarkerView
import com.syqc.maps.utils.BitmapUtil
import com.syqc.maps.utils.MarkerSet
import com.syqc.maps.utils.NaviActivity
import com.syqc.monitor.R
import com.syqc.monitor.databinding.ActivityMapRegion2Binding
import com.syqc.monitor.databinding.IncludeCarMapInfoBinding
import com.syqc.monitor.databinding.IncludeCarOperaBinding
import com.syqc.monitor.popup.DriversPopup
import com.syqc.monitor.popup.LegendPopup3
import com.syqc.monitor.popup.MultiMonitorPopup
import com.syqc.monitor.ui.cars.CarsPopup
import com.syqc.monitor.ui.carsmonitor.CarAdapter
import com.syqc.monitor.ui.carsmonitor.CarAroundActivity
import com.syqc.monitor.ui.set.InfoSet2Activity
import com.syqc.monitor.ui.tyre.TyreInfoActivity
import com.syqc.monitor.utils.ActivityUtil
import com.syqc.utils.ColorUtil
import com.syqc.utils.DataUtil
import com.syqc.utils.Keys
import com.syqc.utils.ToolsUtil
import com.syqc.utils.Units
import com.syqc.videos.TalkPopup
import com.syqc.videos.TalkStatus
import com.syqc.videos.TalkbackUtil
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import java.text.DecimalFormat


class RegionMapActivity : BaseMapLocationActivity<ActivityMapRegion2Binding>(
    ActivityMapRegion2Binding::inflate
) {
    private var isPause = false

    //是否移动
    private var isMove = true

    //是否处理定位
    private var isLoad = false

    //是否显示其他信息
    private var isShowInfo = AppConfigs.isMapInfoOpen

    //是否显示弹窗
    private var isShowPopup = false

    //是否聚合
    private var isBounds = true

    //当前车辆位置
    private var carLatLng: LatLng? = null

    //手机当前位置
    private var phoneLatLng: LatLng? = null

    //定位Marker
    private var mLocationMarker: Marker? = null


    //图例弹窗
    private val mLegendPopup by lazy { LegendPopup3(this) }


    //单车的弹窗
    private val mMultiPopup by lazy { MultiMonitorPopup(this) }

    //驾驶员弹窗
    private val mDriversPopup by lazy { DriversPopup(this) }

    //卡片弹窗
    private val mCarsPopup by lazy {
        CarsPopup(this).apply {
            setOnDismissListener {
                mViewModel.isShowCard(false)
                binding.tvList.isVisible = true
            }
            setCallBack(object : CarsPopup.CallBack {
                override fun callback(carId: String) {
                    binding.tvPlate.isVisible = false
                    mViewModel.carId = carId
                    mViewModel.nowCar()
                    isShowPopup = true
                    isMove = true
                    dismiss()
                }
            })
        }
    }

    //聚合处理
    private val mOverlay by lazy { ClusterOverlay(this, mAMap) }

    private val mViewModel by viewModels<RegionMapVM>()

    //车辆信息详情
    private val mInfoAdapter by lazy { CarInfoAdapter() }


    private lateinit var mOperaVB: IncludeCarOperaBinding
    private lateinit var mInfoVB: IncludeCarMapInfoBinding
    private lateinit var mBarVB: IncludeToolbarBinding

    override fun initMap() {
        MapUtil.initMapSetting(mAMap)
        mAMap.setInfoWindowAdapter(infoAdapter)
        binding.ivCarsTraffic.isSelected = mViewModel.isTraffic
        mAMap.isTrafficEnabled = mViewModel.isTraffic
        initOverlay()
        mAMap.setOnInfoWindowClickListener {
            if (mLocationMarker?.isInfoWindowShown == true)
                mViewModel.gpsDetail?.run {
                    startActivityTo<NaviActivity>(this@RegionMapActivity) {
                        putExtra(Keys.INTENT_PLATE, carPlate)
                        putExtra("eLat", glat)
                        putExtra("eLng", glng)
                        putExtra("bLat", blat)
                        putExtra("bLng", blng)
                    }
                }
        }
        val data = intent.getStringExtra(Keys.INTENT_DATA)
        if (data.isNullOrEmpty()) {
            mViewModel.getRegionById(intent.getStringExtra(Keys.INTENT_OTHER) ?: "")
        } else {
            val poi = GsonUtil.formObject<PoiStati>(data)
            drawCircle(LatLng(poi.glat, poi.glng), poi.radius)
        }
    }

    override fun initView() {
        mOperaVB = IncludeCarOperaBinding.bind(binding.root)
        mInfoVB = IncludeCarMapInfoBinding.bind(binding.root)
        mBarVB = IncludeToolbarBinding.bind(binding.root)
        type = 2
        immersionBar { titleBar(mBarVB.mToolbar) }
        ToolbarHelper.setToolbar(this, intent.getStringExtra(Keys.INTENT_TITLE) ?: "")
        binding.ivCarsAll.isVisible = false
        if (mViewModel.mapType == AMap.MAP_TYPE_NORMAL) {
            binding.tvCarsMapState.setText(R.string.desc_com_map_state_normal)
        } else {
            binding.tvCarsMapState.setText(R.string.desc_com_map_state_satellite)
        }

        if (mViewModel.isPlate) {
            binding.tvCarsState.setText(R.string.desc_car_plate)
        } else {
            binding.tvCarsState.setText(R.string.desc_car_name)
        }

        initAllRecycle()
        initViewModel()
        bindRecycler()
        handOperaEvent()
        handGpsEvent()

        mViewModel.carIds = intent.getStringExtra(Keys.INTENT_ID) ?: ""
        mViewModel.startRefresh()
//        binding.tvList.isVisible=true
        binding.ivCarsAll.isVisible = true
        binding.rlRefresh.isVisible = true
        ToolsUtil.startAmin(binding.ivRefresh)

    }


    override fun setListener() {

        //地图级别 扩大
        binding.ivMapZoomIn.setOnClickListener {
            mAMap.animateCamera(CameraUpdateFactory.zoomOut(), 600, null)
        }
        //地图级别 缩小
        binding.ivMapZoomOut.setOnClickListener {
            mAMap.animateCamera(CameraUpdateFactory.zoomIn(), 600, null)
        }
        //全部车辆列表
        binding.ivCarsAll.setOnClickListener {
            mViewModel.isShowAll = !mViewModel.isShowAll
            mViewModel.showAll()
            isShowAll()
        }
        //交通路况开关
        binding.ivCarsTraffic.setOnClickListener {
            mViewModel.saveTraffic()
            binding.ivCarsTraffic.isSelected = mViewModel.isTraffic
            mAMap.isTrafficEnabled = mViewModel.isTraffic
        }
        //车辆地图切换
        binding.tvCarsMapState.setOnClickListener {
            if (mViewModel.mapType == AMap.MAP_TYPE_NORMAL) {
                mAMap.mapType = AMap.MAP_TYPE_SATELLITE
                mViewModel.saveMapType(AMap.MAP_TYPE_SATELLITE)
                binding.tvCarsMapState.setText(R.string.desc_com_map_state_satellite)
            } else {
                mAMap.mapType = AMap.MAP_TYPE_NORMAL
                mViewModel.saveMapType(AMap.MAP_TYPE_NORMAL)
                binding.tvCarsMapState.setText(R.string.desc_com_map_state_normal)
            }
        }
        //切换车牌和车名
        binding.tvCarsState.setOnClickListener {
            if (mViewModel.isPlate) {
                mViewModel.isPlate = false
                binding.tvCarsState.setText(R.string.desc_car_name)
            } else {
                binding.tvCarsState.setText(R.string.desc_car_plate)
                mViewModel.isPlate = true
            }
            mOverlay.refresh()
            mAllAdapter.notifyDataSetChanged()
            mViewModel.gpsDetail?.run {
                val title = if (mViewModel.isPlate) carPlate else carName
                binding.tvPlate.text = title
                ColorUtil.lineState(mInfoVB.tvOnLine, state)
                ColorUtil.setPlateColor(
                    mInfoVB.tvPlateArea,
                    mInfoVB.tvPlateNum,
                    plateColor,
                    plateColorCode,
                    title
                )
            }
        }

        //卡片列表
        binding.tvList.setOnClickListener {
            binding.tvList.isVisible = false
            mViewModel.isShowCard(true)
            mCarsPopup.show(window.decorView)
        }
        //周边
        binding.tvAround.setOnClickListener {
            startActivityTo<CarAroundActivity>(this) {
                putExtra(Keys.INTENT_CAR_NAME, mViewModel.gpsDetail?.carPlate)
                putExtra(Keys.INTENT_CAR_ID, mViewModel.carId)
            }
        }
        //全显
        binding.tvDisplayAll.setOnClickListener {
            mViewModel.carId = ""
            mOverlay.refreshOne(mViewModel.carId)
            mOperaVB.rlCarsOperate.isVisible = false
            binding.tvAround.isVisible = false
            mInfoVB.llCarInfo.isVisible = false
            binding.tvPlate.isVisible = false
            val bounds = mViewModel.getBounds()
            if (bounds != null) { // 检查 bounds 是否为 null
                MapUtil.showMapBounds(mAMap, bounds)
            }
        }

        //点击后隐藏
        binding.llAllCars.filterFast {
            mViewModel.isShowAll = false
            isShowAll()
        }
    }

    private fun initViewModel() {
        mViewModel.regionLive.observe(this) {
            when (it.shape) {
                "0" -> {
                    drawCircle(it.points, it.radius)
                }

                "1" -> {
                    drawRectangle(it.points)
                }

                "2" -> {
                    drawPolygon(it.points)
                }

                "3" -> {
                    drawLine(it.points)
                }
            }
        }
        mViewModel.toastObserver().observeOn(AndroidSchedulers.mainThread())
            .autoDispose(scopeProvider).subscribe(::toastObserver)
        //全部车辆信息
        mViewModel.allCars.observe(this) {
            mAllAdapter.setList(it)
        }
        //聚合数据
        mViewModel.clusters.observe(this) {
            isLoad = true
            mOverlay.addClusterItems(it, mViewModel.carId)
            if (isBounds) {
                isBounds = false
                val bounds = mViewModel.getBounds()
                if (bounds != null) { // 检查 bounds 是否为 null
                    MapUtil.showMapBounds(mAMap, bounds)
                }
            }
        }
        //卡片分类信息
        mViewModel.gpsType.observe(this) {
            mCarsPopup.refreshData(it, mViewModel.isPlate)
            mCarsPopup.resetTabLayouts(mViewModel.typeNum)
        }
        //图例信息
        mViewModel.legends.observe(this) {
            mLegendPopup.showAtLocation(mOperaVB.ivCarsLegend, it)
        }
        //刷新倒计时
        mViewModel.refreshLive.observe(this) {
            if (it == 1) {
                ToolsUtil.stopAmin(binding.ivRefresh)
                ToolsUtil.startAmin(binding.ivRefresh)
            }
            if (it / 3600 > 0) {
                binding.tvRefreshTime.text = "${it / 60}${getString(R.string.unit_minute_)}"
            } else if (it / 60 > 0) {
                binding.tvRefreshTime.text = "${it / 60}${getString(R.string.unit_minute_)}"
            } else {
                binding.tvRefreshTime.text = "${it}${getString(R.string.unit_second_)}"
            }
        }
        //单车定位信息
        mViewModel.locationLive.observe(this) {
            if (!it) return@observe
            isLoad = true
            mViewModel.gpsDetail?.run {
                carLatLng = LatLng(glat.toDouble(), glng.toDouble())
                if (isShowPopup) {
                    handleGpsInfo()
                    mInfoVB.llCarInfo.isVisible = true
                }
                if (isMove) {
                    isMove = false
                    MapUtil.showLatLngZoom(mAMap, carLatLng!!)
                } else if (AppConfigs.isCenter) {
                    MapUtil.showMapLatLng(mAMap, carLatLng!!)
                }
                mOperaVB.rlCarsOperate.isVisible = true
                binding.tvAround.isVisible = true
                binding.tvPlate.text = if (mViewModel.isPlate) carPlate else carName
            }
            if (mViewModel.isOnlyRefresh) mOverlay.refreshOne(mViewModel.carId)
        }

    }

    /**
     * 设备当前定位结果监听
     */
    override fun onMyLocationChange(location: Location?) {
        if (location?.extras == null) return
        val bundle = location.extras!!["errorCode"] ?: return
        if (bundle != 0) {
            bundle.toastLong(this)
            return
        }
        isShowPopup = false
        binding.tvPlate.isVisible = true
        mInfoVB.llCarInfo.isVisible = false

        val latLng = LatLng(location.latitude, location.longitude)
        phoneLatLng = latLng
        MapUtil.showMapBounds(
            mAMap, mViewModel.getBounds(carLatLng!!, latLng), 300
        )

        if (mLocationMarker == null) {
            mLocationMarker = MapUtil.addAndGetMarker(
                mAMap, latLng, R.mipmap.ic_phone_location
            )
        } else {
            mLocationMarker?.position = latLng
        }
        mLocationMarker!!.showInfoWindow()
        viewHolder?.setRange()
    }

    /**
     * 处理聚合相关
     *
     */
    private fun initOverlay() {
        val bitmapDrawable = ContextCompat.getDrawable(this, R.drawable.bg_blue_yuan)
        //缓存
        lruCache = object : LruCache<String, BitmapDescriptor?>(maxMemory) {
            override fun entryRemoved(
                evicted: Boolean,
                key: String,
                oldValue: BitmapDescriptor?,
                newValue: BitmapDescriptor?
            ) {
                super.entryRemoved(evicted, key, oldValue, newValue)
                oldValue?.recycle()
            }
        }
        mOverlay.setClusterRender(object : ClusterRender {
            override fun getDrawable(num: Int): Drawable {
                return bitmapDrawable!!
            }

            override fun getBitmap(isSingle: Boolean, item: ClusterItem): BitmapDescriptor {
                val key: String = if (item.name == item.plate) {
                    "${item.carId}${item.drct}${item.iconLink}${item.speed}"
                } else {
                    "${item.carId}${item.drct}${item.iconLink}${item.speed}${mViewModel.isPlate}"
                }

                var bitmapDescriptor = lruCache?.get(key)
                if (isSingle) {
                    val markerView = MarkerView(this@RegionMapActivity, MarkerSet.mMarkerSet)
                    markerView.setOnlyMarker(item, mViewModel.isPlate)
                    bitmapDescriptor = BitmapDescriptorFactory.fromView(markerView)
                } else {
                    if (bitmapDescriptor == null) {
                        val markerView = MarkerView(this@RegionMapActivity, MarkerSet.mMarkerSet)
                        markerView.setMarkerInfo(item, mViewModel.isPlate)
                        bitmapDescriptor = BitmapDescriptorFactory.fromView(markerView)
                        lruCache?.put(key, bitmapDescriptor)
                    }
                }
                return bitmapDescriptor!!
            }
        })

        mOverlay.setClusterListener(object : ClusterListener {
            override fun onClusterListener(marker: Marker, cluster: Cluster) {
                if (mAMap.cameraPosition.zoom < 17) {
                    val builder = LatLngBounds.Builder()
                    for (item in cluster.clusterItems) {
                        builder.include(item.latLng)
                    }
                    val latLngBounds = builder.build()
                    MapUtil.showMapBounds(mAMap, latLngBounds)
                } else {
                    if (cluster.clusterCount > 1) {
                        marker.showInfoWindow()
                    }
                }
            }

            override fun onClusterItemListener(marker: Marker, cluster: ClusterItem) {
                if (marker == mLocationMarker) {
                    marker.showInfoWindow()
                } else {
                    isShowPopup = true
                    isMove = true
                    binding.tvPlate.isVisible = false
                    mViewModel.getCarLocation(cluster.carId)
                }
            }
        })
    }

    //处理定位信息View
    private fun bindRecycler() {
        mInfoVB.recyclerCarInfo.layoutManager = LinearLayoutManager(this)
        mInfoVB.recyclerCarInfo.adapter = mInfoAdapter
        handleOper()
    }

    private val runSpeed by lazy { getString(R.string.desc_run_speed) }
    private val dayMile by lazy { getString(R.string.desc_day_mile) }

    //处理定位信息View
    private fun handleGpsInfo() {
        mViewModel.gpsDetail?.run {
            mInfoVB.tvCarRunSpeed.text = "$speed ${Units.speed}\n$runSpeed"
            mInfoVB.tvCarRunStop.text = runStopTime
            mInfoVB.tvCarDayMile.text = "$preMile ${Units.km}\n$dayMile"
            mInfoVB.tvCarTotalMile.text = "$mile ${Units.km}"
            mInfoVB.tvCarTime.text = "${getString(R.string.desc_location_time)}：$time"
            mInfoVB.tvSatl.text = "${getString(R.string.desc_marker_loaction)}${satl.split("-")[0]}"
            mInfoVB.tvSgn.text = "${getString(R.string.desc_marker_sgn)}${sgn.split("-")[0]}"
            ColorUtil.lineState(mInfoVB.tvOnLine, state)
            val title = if (mViewModel.isPlate) carPlate else carName
            ColorUtil.setPlateColor(
                mInfoVB.tvPlateArea,
                mInfoVB.tvPlateNum,
                plateColor,
                plateColorCode,
                title
            )

            val isTalk = mViewModel.talkChannel.isNotEmpty()
            if (isTalk != operInfoAdapter.isCanTalk)
                operInfoAdapter.isCanTalk = isTalk

            if (isShowInfo) handleInfoData()
        }
    }

    //处理操作信息
    private fun handOperaEvent() {
        //手机定位
        mOperaVB.ivCarsPhone.setOnClickListener {
            getPermissions(false)
        }
        //上一辆
        mOperaVB.ivCarsPrevious.filterFast {
            isMove = true
            mViewModel.previousCar()
        }
        //当前车辆
        mOperaVB.ivCarsNow.filterFast {
            binding.tvPlate.isVisible = false
            isShowPopup = true
            isMove = true
            mViewModel.nowCar()
        }
        //下一辆
        mOperaVB.ivCarsNext.filterFast {
            isMove = true
            mViewModel.nextCar()
        }
        //图例
        mOperaVB.ivCarsLegend.setOnClickListener {
            mViewModel.getLegend()
        }

        mMultiPopup.setOnDismissListener {
            GuideControl.isShowMulti = false
        }
    }

    //处理定位信息数据
    private fun handleInfoData() {
        mInfoAdapter.setList(LocationStatusModel.upData(mViewModel.gpsDetail))
    }

    //处理定位信息事件
    private fun handGpsEvent() {
        mInfoVB.ivTyre.isVisible = UserConstant.current_ip != "113.105.152.93"
        mInfoVB.ivUpDown.isSelected = isShowInfo
        if (isShowInfo) {
            handleInfoData()
            mInfoVB.recyclerCarInfo.isVisible = true
        } else {
            mInfoVB.recyclerCarInfo.isVisible = false
        }
        //车辆信息开关
        mInfoVB.ivUpDown.setOnClickListener {
            isShowInfo = !isShowInfo
            mInfoVB.ivUpDown.isSelected = isShowInfo
            if (isShowInfo) {
                handleInfoData()
                mInfoVB.recyclerCarInfo.isVisible = true
            } else {
                mInfoVB.recyclerCarInfo.isVisible = false
            }
        }
        //设置按钮
        mInfoVB.ivCarSet.filterFast {
            startActivityTo<InfoSet2Activity>(this)
        }
        //刷新车辆信息
        mInfoVB.ivCarRefresh.filterFast {
            mViewModel.refreshCar()
        }

        mInfoVB.ivTyre.setOnClickListener {
            mViewModel.gpsDetail?.let {
                val list = LocationStatusModel.getExtsValue(it.exts, "c8")
                if (list.isEmpty()) {
                    showToast(R.string.desc_toast_no_data_tyre)
                    return@setOnClickListener
                }
                val type = object : TypeToken<List<List<String>>>() {}
                val data: List<List<String>> = GsonUtil.gson.fromJson(list, type.type)
                DataUtil.psiTyres = data
                startActivityTo<TyreInfoActivity>(this) {
                    putExtra(Keys.INTENT_TITLE, if (mViewModel.isPlate) it.carPlate else it.carName)
                }
            }
        }
        //信息框关闭
        mInfoVB.ivCarClose.setOnClickListener {
            isShowPopup = false
            mInfoVB.llCarInfo.isVisible = false
            binding.tvPlate.isVisible = true
            if (GuideControl.isShowMulti) mMultiPopup.showAtLocation(
                window.decorView, Gravity.NO_GRAVITY, 0, 0
            )
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////
    private val mCarAdapter = CarAdapter()

    private val infoAdapter = object : AMap.InfoWindowAdapter {
        override fun getInfoWindow(marker: Marker?): View? {
            return null
        }

        override fun getInfoContents(marker: Marker?): View {
            if (marker == mLocationMarker) {
                return getPhoneInfoWindow()
            }
            return getWindowView(marker)
        }
    }

    //聚合弹窗
    private var popupView: View? = null


    private var viewHolder: ViewHolder? = null

    private inner class ViewHolder(view: View) {
        private val df = DecimalFormat("#.0")
        private val tvRangeDesc: TextView = view.findViewById(R.id.tvRangeDesc)
        fun setRange() {
            val range = AMapUtils.calculateLineDistance(phoneLatLng, carLatLng)
            val t =
                if (range > 1000) {
                    "${df.format(range / 1000)} ${getString(R.string.unit_mile_)}"
                } else {
                    "${range.toString().split(".")[0]} ${getString(R.string.unit_rice)}"
                }
            tvRangeDesc.text = getString(R.string.desc_location_now) + "$t"
        }
    }

    private var localView: View? = null
    private fun getPhoneInfoWindow(): View {
        viewHolder =
            if (localView == null) {
                localView = View.inflate(this, R.layout.popup_location, null)
                val holder = ViewHolder(localView!!)
                localView!!.tag = holder
                holder
            } else {
                localView!!.tag as ViewHolder
            }

        viewHolder!!.setRange()
        return localView!!
    }

    fun getWindowView(marker: Marker?): View {

        val cluster = marker?.`object` as? Cluster
        if (popupView == null) {
            popupView = View.inflate(this, R.layout.layout_cars, null)
            val recycler = popupView!!.findViewById<RecyclerView>(R.id.recycleCars)
            recycler.layoutManager = LinearLayoutManager(this)
            recycler.adapter = mCarAdapter
            mCarAdapter.setOnItemClickListener { _, _, position ->
                val item = mCarAdapter.data[position]
                mViewModel.getCarLocation(item.carId)
            }
        }

        mCarAdapter.setList(cluster?.clusterItems)
        return popupView!!
    }


    //////////////////////////////////////////////////////////////////////////////////////////////
    private val mAllAdapter = AllAdapter()
    private fun initAllRecycle() {
        binding.recyclerAll.layoutManager = LinearLayoutManager(this)
        binding.recyclerAll.adapter = mAllAdapter

        mAllAdapter.setOnItemClickListener { adapter, view, position ->
            val item = mAllAdapter.data[position]
            if (ToolsUtil.isNoLocation(item.state) || item.glat.isNullOrEmpty()) {
                R.string.toast_no_location_msg.toast(this)
                return@setOnItemClickListener
            }
            mViewModel.carId = item.carId
            mViewModel.nowCar()
            isShowPopup = true
            isMove = true
            binding.tvPlate.isVisible = false
            mViewModel.isShowAll = false
            isShowAll()
        }

    }

    //////////////////////////////////////////////////////////////////////////////////////////////


    //是否显示全部
    private fun isShowAll() {
        binding.ivCarsAll.isVisible = !mViewModel.isShowAll
        binding.llAllCars.isVisible = mViewModel.isShowAll
    }

    //////////////////////////////////////////////////////////////////////////////////////////
    private var lruCache: LruCache<String, BitmapDescriptor?>? = null
    var maxMemory = (Runtime.getRuntime().maxMemory() / 10240).toInt()

    override fun onResume() {
        super.onResume()
        if (isPause && isLoad) {
            isPause = false
            mViewModel.startRefresh()
        }
        operInfoAdapter.setList(InfoSetModel.getChooseList(FunType.CAS))
    }

    override fun onPause() {
        super.onPause()
        mViewModel.stopRefresh()
        isPause = true
    }

    override fun onDestroy() {
        TalkbackUtil.destroy()
        super.onDestroy()
        BitmapUtil.clearLruCache()
        ToolsUtil.stopAmin(binding.ivRefresh)
        if (mMultiPopup.isShowing) mMultiPopup.dismiss()
    }


    inner class AllAdapter : BaseQuickAdapter<GpsDetail, BaseViewHolder>(R.layout.item_all) {
        override fun convert(holder: BaseViewHolder, item: GpsDetail) {
            holder.setText(R.id.tvCarTitle, if (mViewModel.isPlate) item.carPlate else item.carName)
            holder.getView<ImageView>(R.id.ivCarIcon).loadStringImgError(context, item.iconLink)
        }
    }


    init {
        BitmapUtil.initLruCache()
    }

    ///////////////////////////////////////添加对讲//////////////////////////////////////////////////////
    //是否录音
    private var isRecord = true

    private val talkPopup by lazy {
        TalkPopup(this) {
            isRecord = true
            TalkbackUtil.closeTalk()
        }
    }
    private val operInfoAdapter by lazy { OperInfoAdapter(FunType.CAS) }

    private fun handleOper() {
        mInfoVB.rvType.layoutManager = GridLayoutManager(this, 6)
        mInfoVB.rvType.adapter = operInfoAdapter
        operInfoAdapter.setList(InfoSetModel.getChooseList(FunType.CAS))
        operInfoAdapter.setOnItemClickListener { adapter, view, position ->
            val info = operInfoAdapter.data[position]
            if (!info.isCheckable) {
                R.string.toast_check_other_menu.toast(this)
                return@setOnItemClickListener
            }
            when (info.key) {
                FunKey.FUN_Talk -> {
                    if (!operInfoAdapter.isCanTalk) {
                        R.string.toast_no_channel.toast(this)
                        return@setOnItemClickListener
                    }
                    getAudioPermissions()
                }

                MenuKey.MENU_916 -> {
                    startActivityTo<CarInfoActivity>(this) {
                        putExtra(Keys.INTENT_CAR_ID, mViewModel.carId)
                    }
                }

                FunKey.FUN_NAVI -> {
                    mViewModel.gpsDetail?.run {
                        startActivityTo<NaviActivity>(this@RegionMapActivity) {
                            putExtra(Keys.INTENT_PLATE, carPlate)
                            putExtra("eLat", glat)
                            putExtra("eLng", glng)
                            putExtra("bLat", blat)
                            putExtra("bLng", blng)
                        }
                    }
                }

                FunKey.FUN_CALL -> {
                    if (mViewModel.driverInfo.isNotEmpty()) {
                        if (mViewModel.driverInfo.size == 1) {
                            ToolsUtil.talkPhone(
                                this,
                                mViewModel.driverInfo[0].driverPhone
                            )
                        } else {
                            mDriversPopup.show(
                                this.window.decorView,
                                mViewModel.driverInfo
                            )
                        }
                    } else {
                        R.string.desc_no_phone.toast(this)
                    }
                }

                else -> {
                    InfoSetModel.startFunActivity(
                        this,
                        ActivityUtil.getActivityByKey(info.key),
                        mViewModel.gpsDetail
                    )
                }
            }
        }

        TalkbackUtil.status.autoDispose(scopeProvider).subscribe {
            when (it) {
                TalkStatus.CLOSE -> {
                    talkPopup.setVoiceTitle(R.string.toast_audio_close)
                    talkPopup.dismiss()
                }

                TalkStatus.OPEN -> {
                    talkPopup.shouPopup(window.decorView)
                    talkPopup.setVoiceTitle(R.string.toast_audio_link)
                }

                TalkStatus.SUCCESS -> {
                    talkPopup.setVoiceTitle(R.string.toast_audio_talking)
                }

                TalkStatus.FAILURE -> {
                    talkPopup.setVoiceTitle(TalkbackUtil.toast)
                    mInfoVB.rvType.postDelayed({
                        talkPopup.dismiss()
                    }, 3000)
                }

                else -> {}
            }
        }
        //上传PCM数据网络失败监听
        TalkbackUtil.upload.autoDispose(scopeProvider).subscribe {
            isRecord = true
            TalkbackUtil.closeTalk()
            talkPopup.dismiss()
        }
        TalkbackUtil.image.autoDispose(scopeProvider).subscribe {
            talkPopup.setVoiceImage(it)
        }
        TalkbackUtil.toastLive.observeOn(AndroidSchedulers.mainThread()).autoDispose(scopeProvider)
            .subscribe {
                showToast(it)
            }
    }

    private fun getAudioPermissions() {
        PermissionX.init(this@RegionMapActivity).permissions(
            Manifest.permission.RECORD_AUDIO
        ).request { allGranted, grantedList, deniedList ->
            if (allGranted) {
                isRecord = false
                TalkbackUtil.openTalk(
                    this@RegionMapActivity, mViewModel.carId, mViewModel.talkChannel
                )
            } else {
                getString(
                    R.string.toast_persission_open,
                    getString(R.string.permission_audio)
                ).toast(this@RegionMapActivity)
            }
        }
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////
    /**
     * 画圆
     */
    private fun drawCircle(points: List<Point>, radius: Int) {
        points.forEach {
            val latLng = LatLng(it.glat, it.glng)
            mAMap.addCircle(
                CircleOptions().center(latLng).radius(radius.toDouble()).strokeWidth(6f)
                    .strokeColor(Color.parseColor("#2461f7"))
                    .fillColor(Color.parseColor("#552461f7"))
            )
        }
    }

    /**
     * 画圆
     */
    private fun drawCircle(latLng: LatLng, radius: Int) {
        mAMap.addCircle(
            CircleOptions().center(latLng).radius(radius.toDouble()).strokeWidth(6f)
                .strokeColor(Color.parseColor("#2461f7"))
                .fillColor(Color.parseColor("#552461f7"))
        )
    }

    /**
     * 画多边形
     *
     */
    private fun drawPolygon(points: List<Point>) {
        val list = ArrayList<LatLng>()
        points.forEach {
            list.add(LatLng(it.glat, it.glng))
        }
        // 绘制一个长方形
        mAMap.addPolygon(
            PolygonOptions().addAll(list).strokeWidth(6f)
                .strokeColor(Color.parseColor("#2461f7"))
                .fillColor(Color.parseColor("#552461f7"))
        )
    }

    /**
     * 画四边形
     *
     */
    private fun drawRectangle(points: List<Point>) {
        val list = ArrayList<LatLng>()
        val pointOne = points[0]
        val pointTwo = points[1]
        list.add(LatLng(pointOne.glat, pointOne.glng))
        list.add(LatLng(pointOne.glat, pointTwo.glng))
        list.add(LatLng(pointTwo.glat, pointTwo.glng))
        list.add(LatLng(pointTwo.glat, pointOne.glng))

        // 绘制一个长方形
        mAMap.addPolygon(
            PolygonOptions().addAll(list).strokeWidth(6f)
                .strokeColor(Color.parseColor("#2461f7"))
                .fillColor(Color.parseColor("#552461f7"))
        )
    }

    /**
     * 画线
     */
    private fun drawLine(points: List<Point>) {
        val list = ArrayList<LatLng>()
        points.forEach {
            list.add(LatLng(it.glat, it.glng))
        }
        // 绘制一个长方形
        mAMap.addPolyline(
            PolylineOptions().addAll(list).width(6f).color(Color.parseColor("#2461f7"))
        )
    }
}